﻿using System;
using System.Collections.Generic;
using System.Data;
using System.IO;
using System.Runtime.Serialization.Formatters.Binary;
using System.Text;
using System.Xml;
using Common.Utilities;
using Common.Utilities.Dispatcher;
using Workflows.Components.TextMining.Properties;

namespace Workflows.Components.TextMining.Collapse
{
    /// <summary>
    /// 
    /// </summary>
    [Serializable]
    public class EntityCollapseComponent:WorkflowComponentBase
    {
        #region props
        private EntityCollapseInstruction _Instruction;
        private EntityCollapseOutput _Output;

        public override InstructionBase Instruction
        {
            get { return _Instruction; }
            set { _Instruction =(EntityCollapseInstruction) value; }
        }

        public override ResultBase Output
        {
            get { return _Output; }
            set { _Output =(EntityCollapseOutput) value; }
        }
        
        /// <summary></summary>
        public string EntityName
        {
            get
            {
                return this._Instruction.EntityName;
            }
            set
            {
                this._Instruction.EntityName = value;
            }
        }

        /// <summary></summary>
        public string ConnStr
        {
            get
            {
                return this._Instruction.ConnStr;
            }
            set
            {
                this._Instruction.ConnStr = value;
            }
        }

        /// <summary></summary>
        public string SchemaName
        {
            get
            {
                return this._Instruction.SchemaName;
            }
            set
            {
                this._Instruction.SchemaName = value;
            }
        }

        /// <summary></summary>
        public string TableName
        {
            get
            {
                return this._Instruction.TableName;
            }
            set
            {
                this._Instruction.TableName = value;
            }
        }

        /// <summary></summary>
        public string IDFieldName
        {
            get
            {
                return this._Instruction.IDFieldName;
            }
            set
            {
                this._Instruction.IDFieldName = value;
            }
        }

        /// <summary></summary>
        public Dictionary<string, double> DescriptiveAttributes
        {
            get
            {
                return this._Instruction.DescriptiveAttributes;
            }
            set
            {
                this._Instruction.DescriptiveAttributes = value;
            }
        }

        /// <summary></summary>
        public Dictionary<string, double> AssociativeAttributes
        {
            get
            {
                return this._Instruction.AssociativeAttributes;
            }
            set
            {
                this._Instruction.AssociativeAttributes = value;
            }
        }

        /// <summary></summary>
        public Dictionary<string, double> PenaltiesWhenNotMatched
        {
            get
            {
                return this._Instruction.PenaltiesWhenNotMatched;
            }
            set
            {
                this._Instruction.PenaltiesWhenNotMatched = value;
            }
        }

        /// <summary></summary>
        public Dictionary<string, FieldComparerPointer> FieldComparers
        {
            get
            {
                return this._Instruction.FieldComparers;
            }
            set
            {
                this._Instruction.FieldComparers = value;
            }
        }

        /// <summary></summary>
        public List<string> UnevenlyDistributedFields
        {
            get
            {
                return this._Instruction.UnevenlyDistributedFields;
            }
            set
            {
                this._Instruction.UnevenlyDistributedFields = value;
            }
        }

        /// <summary></summary>
        public double CollapseThreshold
        {
            get
            {
                return this._Instruction.CollapseThreshold;
            }
            set
            {
                this._Instruction.CollapseThreshold = value;
            }
        }


        /// <summary></summary>
        public List<List<string>> OrFilters
        {
            get
            {
                return this._Instruction.OrFilters;
            }
            set
            {
                this._Instruction.OrFilters = value;
            }
        }

        /// <summary></summary>
        public Dictionary<string, string> FieldEncoders
        {
            get
            {
                return this._Instruction.FieldEncoders;
            }
            set
            {
                this._Instruction.FieldEncoders = value;
            }
        }

        /// <summary></summary>
        public string OutputTableName
        {
            get
            {
                return this._Instruction.OutputTableName;
            }
            set
            {
                this._Instruction.OutputTableName = value;
            }
        }

        /// <summary></summary>
        public string CollapsedTableName
        {
            get
            {
                return this._Instruction.CollapsedTableName;
            }
            set
            {
                this._Instruction.CollapsedTableName = value;
            }
        }

        /// <summary></summary>
        public string FieldDistributionSourceTableName
        {
            get
            {
                return this._Instruction.FieldDistributionSourceTableName;
            }
            set
            {
                this._Instruction.FieldDistributionSourceTableName = value;
            }
        }

        /// <summary></summary>
        public List<List<string>> SwappedFieldsCollection
        {
            get
            {
                return this._Instruction.SwappedFieldsCollection;
            }
            set
            {
                this._Instruction.SwappedFieldsCollection = value;
            }
        }

        /// <summary></summary>
        public double AssociateThreshold
        {
            get
            {
                return this._Instruction.AssociateThreshold;
            }
            set
            {
                this._Instruction.AssociateThreshold = value;
            }
        }

        /// <summary></summary>
        public string OverCollapsedFilePath
        {
            get
            {
                return this._Instruction.OverCollapsedFilePath;
            }
            set
            {
                this._Instruction.OverCollapsedFilePath = value;
            }
        }

        /// <summary></summary>
        public string UnderCollapsedFilePath
        {
            get
            {
                return this._Instruction.UnderCollapsedFilePath;
            }
            set
            {
                this._Instruction.UnderCollapsedFilePath = value;
            }
        }

        /// <summary></summary>
        public string FinalResultFilePath
        {
            get
            {
                return this._Instruction.FinalResultFilePath;
            }
            set
            {
                this._Instruction.FinalResultFilePath = value;
            }
        }

        /// <summary></summary>
        public List<CompensaterPointer> Compensaters
        {
            get
            {
                return this._Instruction.Compensaters;
            }
            set
            {
                this._Instruction.Compensaters = value;
            }
        }
        #endregion

        #region ctor
        /// <summary>
        /// 
        /// </summary>
        public EntityCollapseComponent():base()
        {
            this.ComponentActivityType = WorkflowActivityType.SimpleActivity;
            this.ComponentCategory = WorkflowComponentCategory.TextMining.ToString();
            this.ComponentName = "Collapse";
            this.Description = "Collapse entity based on attribute statistics";
            this.ComponentIcon = Resources.calc_SC;
            this.ComponentImage = Resources.calc;

            this._Instruction =
                new EntityCollapseInstruction(
                    this.ComponentID, Guid.Empty,
                    string.Empty, string.Empty, string.Empty,
                    string.Empty, string.Empty,
                    new Dictionary<string, double>(),
                    new Dictionary<string, double>(),
                    new Dictionary<string, double>(),
                    new Dictionary<string, FieldComparerPointer>(),
                    new List<string>(),
                    new List<List<string>>(),
                    new Dictionary<string, string>(), 
                    0.56, string.Empty, string.Empty,
                    string.Empty, new List<List<string>>(), 0.35,
                    string.Empty, string.Empty,
                    string.Empty, new List<CompensaterPointer>());
            this._Output = new EntityCollapseOutput(this.ComponentID, Guid.Empty, 0);
        }
        #endregion

        public override XmlNode Serialize(ref XmlDocument xDoc, ref XmlNode parentNode)
        {
            XmlNode xNode = base.Serialize(ref xDoc, ref parentNode);

            XmlDataUtil.UpdateAttribute(ref xDoc, xNode, "EntityName", this.EntityName);
            XmlDataUtil.UpdateAttribute(ref xDoc, xNode, "ConnStr", this.ConnStr);
            XmlDataUtil.UpdateAttribute(ref xDoc, xNode, "TableName", this.TableName);
            XmlDataUtil.UpdateAttribute(ref xDoc, xNode, "SchemaName",this.SchemaName);
            XmlDataUtil.UpdateAttribute(ref xDoc, xNode, "IDFieldName", this.IDFieldName);
            XmlDataUtil.UpdateAttribute(ref xDoc, xNode, "CollapseThreshold", this.CollapseThreshold.ToString());
            XmlDataUtil.UpdateAttribute(ref xDoc, xNode, "OutputTableName", this.OutputTableName);
            XmlDataUtil.UpdateAttribute(ref xDoc, xNode, "CollapsedTableName", this.CollapsedTableName);
            XmlDataUtil.UpdateAttribute(ref xDoc, xNode, "FieldDistributionSourceTableName", this.FieldDistributionSourceTableName);
            XmlDataUtil.UpdateAttribute(ref xDoc, xNode, "AssociateThreshold", this.AssociateThreshold.ToString());
            XmlDataUtil.UpdateAttribute(ref xDoc, xNode, "UnderCollapsedFilePath", this.UnderCollapsedFilePath);
            XmlDataUtil.UpdateAttribute(ref xDoc, xNode, "OverCollapsedFilePath", this.OverCollapsedFilePath);
            XmlDataUtil.UpdateAttribute(ref xDoc, xNode, "FinalResultFilePath", this.FinalResultFilePath);

            if (this.DescriptiveAttributes != null && this.DescriptiveAttributes.Count > 0)
            {
                XmlNode descFieldRootNode = XmlDataUtil.AddElement(ref xDoc, xNode, "DescriptiveAttributes");
                foreach (string fieldName in this.DescriptiveAttributes.Keys)
                {
                    XmlNode descFieldNode = XmlDataUtil.AddElement(ref xDoc, descFieldRootNode, "DescriptiveAttribute");
                    XmlDataUtil.UpdateAttribute(ref xDoc, descFieldNode, "FieldName", fieldName);
                    XmlDataUtil.UpdateAttribute(ref xDoc, descFieldNode, "Weight",
                                                this.DescriptiveAttributes[fieldName].ToString());
                }
            }
            if (this.AssociativeAttributes != null && this.AssociativeAttributes.Count > 0)
            {
                XmlNode assocFieldRootNode = XmlDataUtil.AddElement(ref xDoc, xNode, "AssociativeAttributes");
                foreach (string fieldName in this.AssociativeAttributes.Keys)
                {
                    XmlNode assocFieldNode = XmlDataUtil.AddElement(ref xDoc, assocFieldRootNode, "AssociativeAttribute");
                    XmlDataUtil.UpdateAttribute(ref xDoc, assocFieldNode, "FieldName", fieldName);
                    XmlDataUtil.UpdateAttribute(ref xDoc, assocFieldNode, "Weight",
                                                this.AssociativeAttributes[fieldName].ToString());
                }
            }
            if (this.PenaltiesWhenNotMatched != null && this.PenaltiesWhenNotMatched.Count > 0)
            {
                XmlNode penaltyRootNode = XmlDataUtil.AddElement(ref xDoc, xNode, "Penalties");
                foreach (string fieldName in this.PenaltiesWhenNotMatched.Keys)
                {
                    XmlNode penaltyNode = XmlDataUtil.AddElement(ref xDoc, penaltyRootNode, "Penalty");
                    XmlDataUtil.UpdateAttribute(ref xDoc, penaltyNode, "FieldName", fieldName);
                    XmlDataUtil.UpdateAttribute(ref xDoc, penaltyNode, "Penalty", this.PenaltiesWhenNotMatched[fieldName].ToString());
                }
            }
            if (this.FieldComparers != null && this.FieldComparers.Count > 0)
            {
                XmlNode fieldCompareRootNode = XmlDataUtil.AddElement(ref xDoc, xNode, "FieldComparers");
                foreach (string fieldName in this.FieldComparers.Keys)
                {
                    XmlNode compareNode = XmlDataUtil.AddElement(ref xDoc, fieldCompareRootNode, "FieldComparer");
                    XmlDataUtil.UpdateAttribute(ref xDoc, compareNode, "FieldName", fieldName);
                    XmlDataUtil.UpdateAttribute(ref xDoc, compareNode, "AssemblyFileName", this.FieldComparers[fieldName].AssemblyFileName);
                    XmlDataUtil.UpdateAttribute(ref xDoc, compareNode, "TypeName", this.FieldComparers[fieldName].TypeFullName);
                }
            }
            if (this.UnevenlyDistributedFields != null && this.UnevenlyDistributedFields.Count > 0)
            {
                XmlNode unevenRootNode = XmlDataUtil.AddElement(ref xDoc, xNode, "UnevenlyDistributedFields");
                foreach (string fieldName in this.UnevenlyDistributedFields)
                {
                    XmlNode unevenFieldNode = XmlDataUtil.AddElement(ref xDoc, unevenRootNode,
                                                                     "UnevenlyDistributedField");
                    XmlDataUtil.UpdateAttribute(ref xDoc, unevenFieldNode, "FieldName", fieldName);
                }
            }
            if (this.OrFilters != null && this.OrFilters.Count > 0)
            {
                XmlNode filterRootNode = XmlDataUtil.AddElement(ref xDoc, xNode, "Filters");
                for (int i = 0; i < this.OrFilters.Count; i++)
                {
                    List<string> addFilters = this.OrFilters[i];
                    XmlNode orFilterNode = XmlDataUtil.AddElement(ref xDoc, filterRootNode, "Or");
                    foreach (string fieldName in addFilters)
                    {
                        XmlNode addFilterNode = XmlDataUtil.AddElement(ref xDoc, orFilterNode, "Add");
                        XmlDataUtil.UpdateAttribute(ref xDoc, addFilterNode, "FieldName", fieldName);
                    }
                }
            }
            XmlNode encoderNodes = XmlDataUtil.AddElement(ref xDoc, xNode, "FieldEncoders");
            if (this.FieldEncoders != null && this.FieldEncoders.Count > 0)
            {
                foreach (string fieldName in this.FieldEncoders.Keys)
                {
                    XmlNode encoderNode = XmlDataUtil.AddElement(ref xDoc, encoderNodes, "FieldEncoder");
                    XmlDataUtil.UpdateAttribute(ref xDoc, encoderNode, "FieldName", fieldName);
                    XmlDataUtil.UpdateAttribute(ref xDoc, encoderNode, "Encoder", this.FieldEncoders[fieldName]);
                }
            }
            if (this.SwappedFieldsCollection != null && this.SwappedFieldsCollection.Count > 0)
            {
                XmlNode swapRootNode = XmlDataUtil.AddElement(ref xDoc, xNode, "SwappedFieldsCollection");
                for (int i = 0; i < this.SwappedFieldsCollection.Count; i++)
                {
                    List<string> swappedFields = this.SwappedFieldsCollection[i];
                    XmlNode swapNode = XmlDataUtil.AddElement(ref xDoc, swapRootNode, "SwappedFields");
                    foreach (string fieldName in swappedFields)
                    {
                        XmlNode swapField = XmlDataUtil.AddElement(ref xDoc, swapNode, "Field");
                        XmlDataUtil.UpdateAttribute(ref xDoc, swapField, "FieldName", fieldName);
                    }
                }
            }

            if (this.Compensaters != null && this.Compensaters.Count > 0)
            {
                XmlNode compensaterRootNode = XmlDataUtil.AddElement(ref xDoc, xNode, "Compensaters");
                foreach (CompensaterPointer compensater in this.Compensaters)
                {
                    XmlNode compensaterNode = XmlDataUtil.AddElement(ref xDoc, compensaterRootNode, "Compensater");
                    XmlDataUtil.UpdateAttribute(ref xDoc, compensaterNode, "AssemblyName", compensater.AssemblyName);
                    XmlDataUtil.UpdateAttribute(ref xDoc, compensaterNode, "TypeFullName", compensater.TypeFullName);
                    XmlDataUtil.UpdateAttribute(ref xDoc, compensaterNode, "ScanSwap", compensater.CanSwap.ToString());
                    XmlDataUtil.UpdateAttribute(ref xDoc, compensaterNode, "FieldNames", StringUtil.ToString(compensater.FieldNames.ToArray()));
                    XmlDataUtil.UpdateAttribute(ref xDoc, compensaterNode, "CompensateScore", compensater.CompensateScore.ToString());
                }
            }

            return xNode;
        }

        public override WorkflowComponentBase Instantiate(XmlNode xNode)
        {
            if (xNode.Attributes.GetNamedItem("Type").Value == this.GetType().FullName)
            {
                EntityCollapseComponent component = base.Instantiate(xNode) as EntityCollapseComponent;

                component.EntityName = XmlDataUtil.GetAttributeValue(xNode, "EntityName", "");
                component.ConnStr = XmlDataUtil.GetAttributeValue(xNode, "ConnStr", "");
                component.SchemaName = XmlDataUtil.GetAttributeValue(xNode, "SchemaName", "");
                component.TableName = XmlDataUtil.GetAttributeValue(xNode, "TableName", "");
                component.IDFieldName = XmlDataUtil.GetAttributeValue(xNode, "IDFieldName", "");
                component.CollapseThreshold =
                    double.Parse(XmlDataUtil.GetAttributeValue(xNode, "CollapseThreshold", "0"));
                component.OutputTableName = XmlDataUtil.GetAttributeValue(xNode, "OutputTableName", "");
                component.CollapsedTableName = XmlDataUtil.GetAttributeValue(xNode, "CollapsedTableName", "");
                component.FieldDistributionSourceTableName =
                    XmlDataUtil.GetAttributeValue(xNode, "FieldDistributionSourceTableName", "");
                component.AssociateThreshold =
                    double.Parse(XmlDataUtil.GetAttributeValue(xNode, "AssociateThreshold", "0.0"));
                component.UnderCollapsedFilePath = XmlDataUtil.GetAttributeValue(xNode, "UnderCollapsedFilePath", "");
                component.OverCollapsedFilePath = XmlDataUtil.GetAttributeValue(xNode, "OverCollapsedFilePath", "");
                component.FinalResultFilePath = XmlDataUtil.GetAttributeValue(xNode, "FinalResultFilePath", "");

                XmlNodeList descNodes = xNode.SelectNodes("DescriptiveAttributes/DescriptiveAttribute");
                component.DescriptiveAttributes = new Dictionary<string, double>();
                if (descNodes != null && descNodes.Count > 0)
                {
                    foreach (XmlNode descNode in descNodes)
                    {
                        string fieldName = XmlDataUtil.GetAttributeValue(descNode, "FieldName", "");
                        double weight = double.Parse(XmlDataUtil.GetAttributeValue(descNode, "Weight", "0"));
                        component.DescriptiveAttributes.Add(fieldName, weight);
                    }
                }

                XmlNodeList assocNodes = xNode.SelectNodes("AssociativeAttributes/AssociativeAttribute");
                component.AssociativeAttributes = new Dictionary<string, double>();
                if (assocNodes != null && assocNodes.Count > 0)
                {
                    foreach (XmlNode assocNode in assocNodes)
                    {
                        string fieldName = XmlDataUtil.GetAttributeValue(assocNode, "FieldName", "");
                        double weight = double.Parse(XmlDataUtil.GetAttributeValue(assocNode, "Weight", "1"));
                        component.AssociativeAttributes.Add(fieldName, weight);
                    }
                }
                
                component.PenaltiesWhenNotMatched = new Dictionary<string, double>();
                XmlNodeList penaltyNodes = xNode.SelectNodes("Penalties/Penalty");
                if (penaltyNodes != null && penaltyNodes.Count > 0)
                {
                    foreach (XmlNode penaltyNode in penaltyNodes)
                    {
                        string fieldName = XmlDataUtil.GetAttributeValue(penaltyNode, "FieldName", "");
                        double penalty = double.Parse(XmlDataUtil.GetAttributeValue(penaltyNode, "Penalty", "0.0"));
                        component.PenaltiesWhenNotMatched.Add(fieldName, penalty);
                    }
                }

                component.FieldComparers = new Dictionary<string, FieldComparerPointer>();
                XmlNodeList compareNodes = xNode.SelectNodes("FieldComparers/FieldComparer");
                if (compareNodes != null && compareNodes.Count > 0)
                {
                    foreach (XmlNode compareNode in compareNodes)
                    {
                        string fieldName = XmlDataUtil.GetAttributeValue(compareNode, "FieldName", "");
                        string assemFileName = XmlDataUtil.GetAttributeValue(compareNode, "AssemblyFileName", "");
                        string typeName = XmlDataUtil.GetAttributeValue(compareNode, "TypeName", "");
                        FieldComparerPointer comparer = new FieldComparerPointer();
                        comparer.AssemblyFileName = assemFileName;
                        comparer.TypeFullName = typeName;
                        component.FieldComparers.Add(fieldName, comparer);
                    }
                }

                component.UnevenlyDistributedFields = new List<string>();
                XmlNodeList unevenFieldNodes = xNode.SelectNodes("UnevenlyDistributedFields/UnevenlyDistributedField");
                if (unevenFieldNodes != null && unevenFieldNodes.Count > 0)
                {
                    foreach (XmlNode unevenNode in unevenFieldNodes)
                    {
                        component.UnevenlyDistributedFields.Add(XmlDataUtil.GetAttributeValue(unevenNode, "FieldName",
                                                                                                ""));
                    }
                }
                
                component.OrFilters = new List<List<string>>();
                XmlNodeList orNodes = xNode.SelectNodes("Filters/Or");
                if (orNodes != null && orNodes.Count > 0)
                {
                    foreach (XmlNode orNode in orNodes)
                    {
                        List<string> addFilters = new List<string>();
                        foreach (XmlNode addNode in orNode.ChildNodes)
                        {
                            string fieldName = XmlDataUtil.GetAttributeValue(addNode, "FieldName", "");
                            addFilters.Add(fieldName);
                        }
                        if (addFilters.Count > 0)
                        {
                            component.OrFilters.Add(addFilters);
                        }
                    }
                }

                component.FieldEncoders = new Dictionary<string, string>();
                XmlNodeList encodeNodes = xNode.SelectNodes("FieldEncoders/FieldEncoder");
                if (encodeNodes != null && encodeNodes.Count > 0)
                {
                    foreach (XmlNode encodeNode in encodeNodes)
                    {
                        string fieldName = XmlDataUtil.GetAttributeValue(encodeNode, "FieldName", "");
                        string encoder = XmlDataUtil.GetAttributeValue(encodeNode, "Encoder", "");
                        component.FieldEncoders.Add(fieldName, encoder);
                    }
                }
                
                component.SwappedFieldsCollection = new List<List<string>>();
                XmlNodeList swapNodes = xNode.SelectNodes("SwappedFieldsCollection/SwappedFields");
                if (swapNodes != null && swapNodes.Count > 0)
                {
                    foreach (XmlNode swapNode in swapNodes)
                    {
                        List<string> swappedFields = new List<string>();
                        foreach (XmlNode fieldNode in swapNode.ChildNodes)
                        {
                            string fieldName = XmlDataUtil.GetAttributeValue(fieldNode, "FieldName", "");
                            swappedFields.Add(fieldName);
                        }
                        component.SwappedFieldsCollection.Add(swappedFields);
                    }
                }

                component.Compensaters = new List<CompensaterPointer>();
                XmlNodeList compensateNodes = xNode.SelectNodes("Compensaters/Compensater");
                if (compensateNodes != null && compensateNodes.Count > 0)
                {
                    foreach (XmlNode compensateNode in compensateNodes)
                    {
                        CompensaterPointer compensater = new CompensaterPointer();
                        compensater.AssemblyName = XmlDataUtil.GetAttributeValue(compensateNode, "AssemblyName", "");
                        compensater.TypeFullName = XmlDataUtil.GetAttributeValue(compensateNode, "TypeFullName", "");
                        compensater.CanSwap = bool.Parse(XmlDataUtil.GetAttributeValue(compensateNode, "CanSwap", false.ToString()));
                        compensater.FieldNames = new List<string>();
                        string[] fieldNames = StringUtil.Split(XmlDataUtil.GetAttributeValue(compensateNode, "FieldNames", ""));
                        if (fieldNames != null && fieldNames.Length > 0)
                        {
                            compensater.FieldNames.AddRange(fieldNames);
                        }
                        compensater.CompensateScore = double.Parse(XmlDataUtil.GetAttributeValue(compensateNode, "CompensateScore", "0.0"));
                        component.Compensaters.Add(compensater);
                    }
                }
                
                return component;
            }
            else
            {
                throw new Exception("Unable to instantiate email: invalid type specified in xml node");
            }
        }

        #region serialization
        /// <summary>
        /// 
        /// </summary>
        /// <param name="fieldValues"></param>
        /// <returns></returns>
        private string SerialzieFieldValue(string[] fieldValues)
        {
            string value = null;
            BinaryFormatter bSerializer = new BinaryFormatter();
            string tmpFilePath = FileUtil.GetWindowsAppTempFilePath("ORMapping", "orm");
            FileStream fs = File.OpenWrite(tmpFilePath);
            bSerializer.Serialize(fs, fieldValues);
            fs.Close();

            fs = File.OpenRead(tmpFilePath);
            byte[] contents = new byte[fs.Length];
            fs.Read(contents, 0, contents.Length);
            fs.Close();
            value = Base64Util.EncodeAsBase64(contents);

            File.Delete(tmpFilePath);

            return value;
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="serializedString"></param>
        /// <returns></returns>
        private string[] InstantiateFieldValue(string serializedString)
        {
            string[] fieldValues = null;
            BinaryFormatter bSerializer2 = new BinaryFormatter();
            string tmpFilePath = FileUtil.GetWindowsAppTempFilePath("ORMapping", "orm");
            FileStream fs2 = File.OpenWrite(tmpFilePath);
            byte[] contents2 = Base64Util.DecodeAsBytes(serializedString);
            fs2.Write(contents2, 0, contents2.Length);
            fs2.Flush();
            fs2.Close();
            fs2 = File.OpenRead(tmpFilePath);
            fieldValues = (string[])bSerializer2.Deserialize(fs2);
            fs2.Close();
            File.Delete(tmpFilePath);

            return fieldValues;
        }
        #endregion
    }
}
